# -*- coding: utf8 -*-
# -*- version: 3.12.2 -*-
# -*- date: 2024-6-13 -*-

# 命令行处理
import sys

# from typing import Callable, Self, Optional
# python 3.8 无 Self，3.9 引入
from typing import Callable, Optional
from uymas import zy


def get_args_index(index: int = 1, default_value: str = '') -> str:
    """
    获取命令行参数指定类型
    """
    if len(sys.argv) <= index:
        return default_value

    try_value = sys.argv[index].strip()
    if try_value:
        return try_value

    return default_value


class Option:
    def __init__(self, args: Optional = None):
        self._data: dict[str, list[str]] = {}
        self._option: list[str] = []
        # 命令
        self.command: str = ""
        # 动作
        self.action: str = ""
        self._args = args if args else sys.argv
        self._parse()

    def _parse(self):
        """
        命令解析
        """
        late_opt = ''
        for i in range(len(self._args)):
            if i == 0:
                continue
            arg = self._args[i].strip()
            if not arg:
                continue

            option_index = arg.find("--")
            if option_index == 0:
                late_opt = arg[2:]
                self._push(late_opt)
                continue

            option_index = arg.find("-")
            if option_index == 0:
                late_opt = arg[1:]
                v_list = list(late_opt)
                self._push(None, *v_list)
                late_opt = v_list[len(v_list) - 1]
                continue

            if i == 1:
                self.command = arg
                continue
            if i == 2 and self.command:
                self.action = arg
                continue

            # 赋值到，data中
            if late_opt:
                self._equal(arg, late_opt)

    def _push(self, name: Optional[str] = None, *args: list[str]):
        """
        保存选项
        :param name:
        :param args:
        :return:
        """
        if name:
            self._option.append(name)

        for arg in args:
            if not arg:
                continue
            self._option.append(arg)

    def _equal(self, value: str, *keys: list[str]):
        """
        保存等式
        :param value:
        :param keys:
        :return:
        """
        for key in keys:
            if key not in self._option:
                self._option.append(key)

            value_list = []
            if key in self._data:
                value_list = self._data[key]
            value_list.append(value)
            self._data[key] = value_list

    def get(self, *args: str, seq='') -> (str, bool):
        """
        获取值
        """
        value_list = []
        exist = False
        for arg in args:
            if arg in self._data:
                value_list = self._data[arg]
                exist = True
                break

        return seq.join(value_list), exist

    def get_raw(self, *args: str, def_str: str = '', seq='') -> str:
        """
        读取原始参数
        :param seq:  链接符号
        :param args: 选项名称
        :param def_str: 默认字符串
        :return:
        """
        v_raw, exist = self.get(*args, seq=seq)
        if not exist:
            return def_str
        if not v_raw:
            return def_str
        return v_raw

    def get_int(self, *args: str, def_int: int = 0):
        """
        获取整形数据
        """
        int_str, exits = self.get(*args)
        if exits:
            return int(int_str)
        return def_int

    def contains(self, *args: str) -> bool:
        """
        判断选项是否存在
        :param args:
        :return:
        """
        for arg in args:
            if arg in self._option:
                return True

        return False

    def get_args(self) -> list[str]:
        """
        获取当前的参数
        :return:
        """
        return self._args


def _uymas_index():
    """
    默认命令
    """
    print("欢迎使用 Uymas 命令行解析程序")
    print("您可注册默认方法")
    print()
    print(" {}/{}".format(zy.VERSION, zy.RELEASE))


def _uymas_unmatch(opt: Option):
    """
    默认命令不存在
    """
    print("[ERR] 糟糕，{} 不存在".format(opt.command))
    print()
    print("{}/{}".format(zy.VERSION, zy.RELEASE))


class Uymas:
    """
    命令行解析
    """

    def __init__(self):
        self._args: list[str] = sys.argv
        # 注册
        self._register: dict[str, Callable[[Optional[Option]], None]] = {}
        self._index: Callable[[Optional[Option]], None] = _uymas_index
        self._unmatch: Callable[[Optional[Option]], None] = _uymas_unmatch
        self._option: Optional[Option] = None

        # hook
        self._hook_before: Optional[Callable[[Optional[Option]], None]] = None
        self._hook_end: Optional[Callable[[Optional[Option]], None]] = None

    def _router(self, *args):
        """
        路由
        :return:
        """
        self._option = Option(args) if len(args) > 0 else Option()
        option = self._option

        command = option.command
        if command and command in self._register:
            if self._hook_before:
                self._hook_before(option)
            self._register[command](option)
            if self._hook_end:
                self._hook_end(option)
            return

        if command:
            if self._hook_before:
                self._hook_before(option)
            self._unmatch(option)
            if self._hook_end:
                self._hook_end(option)
            return

        # index
        command_index = self._index if self._index else _uymas_index
        if self._hook_before:
            self._hook_before(option)
        command_index(option)
        if self._hook_end:
            self._hook_end(option)

    def register(self, *args, runnable: Callable[[Option], None]) -> any:
        """
        方法注册
        :param args:
        :param runnable:
        :return:
        """
        for arg in args:
            self._register[arg] = runnable
        return self

    def index(self, runnable: Callable[[Option], None]) -> any:
        """
        默认方法
        :param runnable:
        :return:
        """
        self._index = runnable
        return self

    def unmatch(self, runnable: Callable[[Option], None]) -> any:
        """
        默认方法
        :param runnable:
        :return:
        """
        self._unmatch = runnable
        return self

    def hook_before(self, runnable: Callable[[Option], None]) -> any:
        """
        命令执行前的 hook
        :return:
        """

        self._hook_before = runnable
        return self

    def hook_end(self, runnable: Callable[[Option], None]) -> any:
        """
        命令执行前的 hook
        :return:
        """
        self._hook_end = runnable
        return self

    def run(self, *args):
        """
        执行
        :return:
        """
        self._router(*args)
